/**
 *
 */
package com.whosly.rapid.lang.thread.executor;

import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

import com.whosly.api.constant.ConventionsX;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;

import com.whosly.rapid.lang.thread.support.InheritableThreadHolder;

import lombok.extern.slf4j.Slf4j;

/**
 * @author yueny09 <yueny09@163.com>
 *
 * @DATE 2017年11月12日 下午1:03:17
 *
 */
@Slf4j
@Deprecated
public abstract class AbstractTraceAwareThreadPool extends ThreadPoolExecutor {//MonitorThreadPoolExecutor
	/**
	 * @param corePoolSize
	 * @param maximumPoolSize
	 * @param keepAliveTime
	 * @param unit
	 * @param workQueue
	 */
	public AbstractTraceAwareThreadPool(final int corePoolSize, final int maximumPoolSize, final long keepAliveTime,
			final TimeUnit unit, final BlockingQueue<Runnable> workQueue) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
	}

	/**
	 * @param corePoolSize
	 * @param maximumPoolSize
	 * @param keepAliveTime
	 * @param unit
	 * @param workQueue
	 * @param handler
	 */
	public AbstractTraceAwareThreadPool(final int corePoolSize, final int maximumPoolSize, final long keepAliveTime,
			final TimeUnit unit, final BlockingQueue<Runnable> workQueue, final RejectedExecutionHandler handler) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
	}

	/**
	 * @param corePoolSize
	 * @param maximumPoolSize
	 * @param keepAliveTime
	 * @param unit
	 * @param workQueue
	 * @param threadFactory
	 */
	public AbstractTraceAwareThreadPool(final int corePoolSize, final int maximumPoolSize, final long keepAliveTime,
			final TimeUnit unit, final BlockingQueue<Runnable> workQueue, final ThreadFactory threadFactory) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
	}

	/**
	 * @param corePoolSize
	 * @param maximumPoolSize
	 * @param keepAliveTime
	 * @param unit
	 * @param workQueue
	 * @param threadFactory
	 * @param handler
	 */
	public AbstractTraceAwareThreadPool(final int corePoolSize, final int maximumPoolSize, final long keepAliveTime,
			final TimeUnit unit, final BlockingQueue<Runnable> workQueue, final ThreadFactory threadFactory,
			final RejectedExecutionHandler handler) {
		super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * java.util.concurrent.ThreadPoolExecutor#afterExecute(java.lang.Runnable,
	 * java.lang.Throwable)
	 */
	@Override
	protected void afterExecute(final Runnable r, final Throwable t) {
		// getTaskCount() 线程池中线程被执行的次数

		log.info("{}/{}afterExecute and remove mdc~~", Thread.currentThread().getId(), getActiveCount());
		removeMdcLogId();

		super.afterExecute(r, t);
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see
	 * java.util.concurrent.ThreadPoolExecutor#beforeExecute(java.lang.Thread,
	 * java.lang.Runnable)
	 */
	@Override
	protected void beforeExecute(final Thread t, final Runnable r) {
		injectLogId();
		log.info("{}/{}子线程启动前注入新的mdc上下文~", Thread.currentThread().getId(), getActiveCount());

		super.beforeExecute(t, r);
	}

	private String injectLogId() {
		String parentLogId = InheritableThreadHolder.get().getLogId();
		if (StringUtils.isBlank(parentLogId)) {
			parentLogId = "-";
		}

		// as traceId
		MDC.put(ConventionsX.CTX_TRACE_ID_MDC, parentLogId);

		// 生成当前线程的logId
		final String logId = StringUtils.remove(UUID.randomUUID().toString(), "-");
		MDC.put(ConventionsX.CTX_LOG_ID_MDC, logId);

		return logId;
	}

	/**
	 * 移除MDC的 logId 信息
	 *
	 * @return 移除的事件信息 logId
	 */
	private String removeMdcLogId() {
		final String logId = MDC.get(ConventionsX.CTX_LOG_ID_MDC);
		if (StringUtils.isEmpty(logId)) {
			return "";
		}

		// 移除当前线程的logId，但不动父线程信息
		MDC.remove(ConventionsX.CTX_LOG_ID_MDC);

		// 只剩下一个活跃的线程，则清空上下文信息
		if (getActiveCount() == 1) {

		}
		return logId;
	}

	/*
	 * (non-Javadoc)
	 *
	 * @see java.util.concurrent.ThreadPoolExecutor#terminated()
	 */
	@Override
	protected void terminated() {
		// 终态，terminated()执行完成。
		super.terminated();

		log.info("{}/terminated", Thread.currentThread().getId());
	}

}
